/**
 * Euclid GUI
 * 
 * @author Jon Ludwig
 */
package Euclid;

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;
import java.util.LinkedList;

import java.io.*;


@SuppressWarnings("serial")
public class EuclidUI extends JFrame {

	// UI
	private JTextField txtInput;
	private JList jlResults;
	private JScrollPane scrollpane;
	private DefaultListModel listmodel;
	
	EuclidEngine engine;
	
	LinkedList<String> history;
	int history_index;
	final int MAX_HISTORY = 20;
	
	private String latex_path = "/usr/texbin/latex";
	private String dvipng_path = "/usr/texbin/dvipng";
	
	/**
	 * Default constructor
	 */
	public EuclidUI()
	{
		super("Euclid");
		
		setSize(new Dimension(400, 300));
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		buildUI();
		
		engine = new EuclidEngine();
		history = new LinkedList<String>();
		history_index = 0;
	}
	
	/**
	 * Build the user interface
	 */
	public void buildUI()
	{
		Container p = getContentPane();
		
		p.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		c.gridx = 0;
		c.gridy = 0;
		c.weightx = 1.0;
		c.weighty = 1.0;
		c.fill = GridBagConstraints.BOTH;
		
		listmodel = new DefaultListModel();
		jlResults = new JList(listmodel);
		jlResults.setDragEnabled(true);
		
		scrollpane = new JScrollPane(jlResults);
		p.add(scrollpane, c);
		
		c.gridy++;
		c.weighty = 0.0;
		txtInput = new JTextField();
		txtInput.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				calculate();
			}
		});
		txtInput.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_UP) {
					if (history_index <= 0) history_index = history.size();
					txtInput.setText(history.get(--history_index));
				}
				else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
					if (history_index >= history.size()-1) history_index = -1;
					txtInput.setText(history.get(++history_index));
				}
			}
		});
		p.add(txtInput, c);
		
		txtInput.requestFocusInWindow();
	}
	
	/**
	 * 
	 */
	public void calculate()
	{
		String input = txtInput.getText();
		
		try {
			VarType v = engine.calculate(input);
			
			if (v == null) throw new Exception();
			
			System.out.println("TeX: " + v.closeFormula());
	        
			File temptex = new File("euclid.tex");
	        File tempdvi = new File("euclid.dvi");
	        File temppng = new File("euclid.png");
	        temptex.deleteOnExit();
	        tempdvi.deleteOnExit();
	        temppng.deleteOnExit();
	        ProcessBuilder dvipb = new ProcessBuilder(latex_path, temptex.getName());
	        ProcessBuilder pngpb = new ProcessBuilder(dvipng_path, tempdvi.getName(),
	        		"-o", temppng.getName(),
	        		"-Ttight",
	        		"-x1440");
	        
	        // write tex
	        if (temptex.exists()) temptex.delete();
	        PrintWriter out = new PrintWriter(new FileOutputStream(temptex, false));
	        out.print("\\documentclass{article}\n" +
	        		"\\usepackage{amsmath}\n" +
	        		"\\usepackage{verbatim}\n" +
	        		"\\begin{document}\n" +
	        		"\\thispagestyle{empty}\n" +
	        		"\\begin{displaymath}\n");
	        out.println(v.closeFormula());
	        out.print("\\end{displaymath}\n" +
	        		"\\end{document}");
	        out.close();
	        
	        Process dvi = dvipb.start();
	        dvi.getOutputStream().close();
	        dvi.waitFor();
	        
	        Process png = pngpb.start();
	        png.waitFor();
	        
	        //System.out.println(v.formula);
	        //TeXIcon icon = new TeXFormula(v.closeFormula()).createTeXIcon(TeXConstants.STYLE_DISPLAY, 20);
	        //Insets in = new Insets(10, 10, 10, 10);
	        //icon.setInsets(in);
	        
	        TeXImage icon = new TeXImage(v.closeFormula());
	        icon.setImage(Toolkit.getDefaultToolkit().createImage(temppng.getName()));
	        listmodel.addElement(icon);
	        txtInput.setText("");
	        
	        if (v instanceof ActiveVarType)
	        	((ActiveVarType)v).activate();
	        
	        history.add(input);
	        if (history.size() >= MAX_HISTORY)
	        	history.removeFirst();
	        history_index = history.size();
	        
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("Bad Input!\n");
			
			listmodel.addElement("Bad Input!");
		}

        jlResults.ensureIndexIsVisible(listmodel.size()-1);
	}
	
	/**
	 * Main entry point
	 * 
	 * @param args command line arguments
	 */
	public static void main(String[] args) {
		EuclidUI e = new EuclidUI();
		e.setVisible(true);
	}
	
	private class TeXImage extends ImageIcon {
		private String formula;
		
		public TeXImage(String formula) {
			super();
			this.formula = formula;
		}
		
		public String toString() {
			return formula;
		}
	}
}
